package top.itaso.app.ui.camera;

import android.content.Context;
import android.content.res.Configuration;
import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.constraintlayout.widget.ConstraintLayout;

import java.io.File;
import java.io.IOException;
import java.util.Date;

import top.itaso.lib.alog.ALog;
import top.itaso.lib.common.DateTimeUtils;
import top.itaso.lib.common.DeviceUtils;
import top.itaso.lib.common.FileUtils;

/**
 * @Description: 调用系统摄像头并自定义预览
 * @Author itsdf07
 * @E-Mail 923255742@qq.com
 * @Gitee https://gitee.com/itsdf07
 * @Date 2022/1/4
 */
public class TakePhotoSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
    private static final String TAG = "TakePhotoSurfaceView";
    private Camera mCamera;
    private SurfaceHolder mSurfaceHolder;

    private ITakePhotoCallback callback;

    private boolean isTaking = false;
    private String mTakePhotoName = "";

    public interface ITakePhotoCallback {
        void onTakePhotoOver(String filePath);

        void onTakePhotoErr(int errCode, String errmsg);
    }

    private static final int TAKEPHOTO_FAILURED = 0;
    private static final int TAKEPHOTO_SUCCESS = 1;

    private Handler mUIHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            if (callback == null) {
                return;
            }
            String takePhotoMsg = (String) msg.obj;
            switch (msg.what) {
                case TAKEPHOTO_FAILURED:
                    callback.onTakePhotoErr(msg.arg1, takePhotoMsg);
                    break;
                case TAKEPHOTO_SUCCESS:
                    callback.onTakePhotoOver(takePhotoMsg);
                    break;
            }
        }
    };

    public TakePhotoSurfaceView(Context context) {
        this(context, null);
    }

    public TakePhotoSurfaceView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public TakePhotoSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mSurfaceHolder = this.getHolder();
        mSurfaceHolder.addCallback(this);
        setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                camearAutoFocus(mCamera);
                return false;
            }
        });
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        ALog.dTag(TAG, "surfaceCreated:......");
        try {
            mCamera = Camera.open();
            mCamera.setPreviewDisplay(holder); //camera关联到SurfaceView
            mCamera.setDisplayOrientation(90); //旋转90度:
            Camera.Parameters params = mCamera.getParameters();
            params.setPictureFormat(ImageFormat.JPEG);
            params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
            mCamera.setParameters(params);

            mCamera.startPreview(); //开始预览
            camearAutoFocus(mCamera);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        boolean isPortrait = getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
        Camera.Parameters params = mCamera.getParameters();
        Camera.Size previewSize = params.getPreviewSize();    // 当前 Camera 分辨
        ALog.dTag(TAG, "surfaceChanged:format=%s,width=%s,height=%s,isPortrait=%s,previewSize.height=%s,previewSize.width=%s", format, width, height, isPortrait, previewSize.height, previewSize.width);
        int[] screenParams = DeviceUtils.getScreenParams(getContext());
        int previewHeight;
        int previewWidth;
        if (isPortrait) {
            previewWidth = screenParams[0];
            previewHeight = previewSize.width * previewWidth / previewSize.height;
        } else {
            previewHeight = screenParams[1];
            previewWidth = previewHeight * previewSize.height / previewSize.width;
        }
        //横竖屏切换的时候刷新相机预览 SurfaceView
        ConstraintLayout.LayoutParams cameraLayout = new ConstraintLayout.LayoutParams(previewWidth, previewHeight);
        this.setLayoutParams(cameraLayout);
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        ALog.dTag(TAG, "surfaceDestroyed:......");
        if (mCamera != null) {
            try {
                mCamera.setPreviewCallback(null);
                mCamera.stopPreview();
                mCamera.release();
                mCamera = null;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public void takePhoto(String fileName, ITakePhotoCallback callback) {
        if (isTaking) {
            Message takePhotoMsg = Message.obtain();
            takePhotoMsg.what = TAKEPHOTO_FAILURED;
            takePhotoMsg.arg1 = 0;
            takePhotoMsg.obj = "不要猴急，上一张照片正在保存中，请稍候";
            mUIHandler.sendMessage(takePhotoMsg);
            return;
        }
        this.callback = callback;
        isTaking = true;
        mTakePhotoName = fileName;
        mCamera.takePicture(null, null, mPictureCallback);
    }

    //第三个PictureCallback接口回调,通过data[]保持图片数据信息
    private Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            ALog.dTag(TAG, "data:%s", data.length);
            //TODO 建议使用AsyncTask或者使用线程池管理
            new Thread(new Runnable() {
                @Override
                public void run() {
                    //照片存储路径=/storage/emulated/0/Android/data/top.itaso.app/files/Download/take_photo_20220113152543.jpg
                    String ROOTPATH_DIRECTORY_DOWNLOADS = getContext().getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString();
                    String filePath = ROOTPATH_DIRECTORY_DOWNLOADS + File.separator + mTakePhotoName + "_" + DateTimeUtils.formatDateTimeStyle(new Date().getTime(), DateTimeUtils.EDateStyle.YYYYMMDDHHMMSS3) + ".jpg";
                    ALog.dTag(TAG, "照片存储路径=%s", filePath);
                    File picImg = FileUtils.getFileByDir(filePath);
                    boolean isSuccess = FileUtils.write2File(picImg, data, true);
                    isTaking = false;
                    Message takePhotoMsg = Message.obtain();
                    if (isSuccess) {
                        takePhotoMsg.what = TAKEPHOTO_SUCCESS;
                        takePhotoMsg.obj = filePath;
                    } else {
                        takePhotoMsg.what = TAKEPHOTO_FAILURED;
                        takePhotoMsg.arg1 = 1;
                        takePhotoMsg.obj = "照片保存失败";
                    }
                    mUIHandler.sendMessage(takePhotoMsg);
                }
            }).start();
            camera.startPreview(); //拍完继续预览
            camearAutoFocus(camera);
        }
    };

    /**
     * 设置相机自动聚焦
     *
     * @param camera
     */
    private void camearAutoFocus(Camera camera) {
        camera.autoFocus(new Camera.AutoFocusCallback() {
            public void onAutoFocus(boolean success, Camera camera) {
                if (success) {
                    ALog.dTag(TAG, "surfaceCreated:聚焦成功 !!");
                } else {
                    ALog.dTag(TAG, "surfaceCreated:聚焦失败 !!");
                }
            }
        });
    }
}
